/*******************************************************************************
 * Copyright (c) 2008-2009 zhang yuexiang.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package org.xfeep.asura.bootstrap;


import java.util.Map;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

import org.xfeep.asura.core.ComponentDefinition;
import org.xfeep.asura.core.ContractType;
import org.xfeep.asura.core.MultiplicityType;
import org.xfeep.asura.core.ReferenceDefinition;
import org.xfeep.asura.core.match.SmartMatcher;
import org.xfeep.asura.core.reflect.TypeInfoUtil;
import org.xfeep.asura.core.reflect.TypeItem;

@XmlType
public class ReferenceDefinitionInfo {
	
	@XmlAttribute
	public boolean required = true;
	@XmlAttribute
	public String name;
	@XmlAttribute
	public ContractType contractType = ContractType.CAREFUL;
	@XmlAttribute
	public String matcher = "";
	@XmlAttribute
	public int order = 0;

	public ReferenceDefinition createReferenceDefinition(ComponentDefinition componentDefinition,  Map<String, TypeItem> itemMap) {
		ReferenceDefinition rd = new ReferenceDefinition();
		rd.setComponentDefinition(componentDefinition);
		rd.setName(name);
		TypeItem bind = itemMap.get(name);
		rd.setBind (bind);
	
		Class<?> type = bind.getType();
		if (type.isArray() || TypeInfoUtil.isCollection(type)){
			rd.setServiceClass( bind.getMemberTypes()[0] );
			rd.setMultiplicityType( required ? MultiplicityType.ONE_N : MultiplicityType.ZERO_N );
		}else {
			rd.setServiceClass(type);
			rd.setMultiplicityType(required ? MultiplicityType.ONE_ONE : MultiplicityType.ZERO_ONE );
		}
		if (matcher.length() > 0){
			rd.setMatcher( SmartMatcher.getMatcher(matcher, componentDefinition.getImplement()) );
		}
		rd.setContractType ( contractType );
		rd.setOrder(order);
		return rd;
		
	}
	
	public static ReferenceDefinitionInfo convert(ReferenceDefinition rd) {
		ReferenceDefinitionInfo rdi = new ReferenceDefinitionInfo();
		rdi.name = rd.getName();
		rdi.required = rd.getMultiplicityType().isRequired();
		rdi.contractType = rd.getContractType();
		if (rd.getMatcher() != null){
			rdi.matcher = rd.getMatcher().toString();
		}
		rdi.order = rd.getOrder();
		return rdi;
	}
	
}
